#include "ParserDeJugadas.h"
#include "JuegoServerImp.h"
#include "JugadorExistenteException.h"
#include "FabricaDeJugadores.h"
#include "MsgUtils.h"
#include "MensajeChat.h"
#include "JugadorExistenteException.h"
#include "MensajeDeExcepcion.h"
#include "guard.h"
#include <cstdlib>
#include <iostream>

ParserDeJugadas::ParserDeJugadas(JuegoServerImp* juego) : xmlpp::SaxParser()
{
	this->juego = juego;
	this->jugador = NULL;
}

ParserDeJugadas::~ParserDeJugadas()
{
}

ParserDeJugadas::ParserDeJugadas(JuegoServerImp* juego, Jugador* jugador, Mutex* mutex_juego) : xmlpp::SaxParser() {
	this->juego = juego;
	this->jugador = jugador;
	this->mutex_juego = mutex_juego;
}

void ParserDeJugadas::on_start_element(const Glib::ustring& name,
                                   const AttributeList& attributes)
{
	Guard guard(mutex_juego);
	if (name.compare("unirse") == 0) {
		unirse(attributes);
	}
	else if (name.compare("getTextura") == 0) {
		juego->getServer()->enviarTextura(jugador);
	}
	else if (name.compare("getMapa") == 0) {
		juego->getServer()->enviarMapa(jugador);
	}
	else if (name.compare("chat") == 0) {
		broadcastMensajeDeChat(attributes);
	}
	else if (name.compare("realizarAtaque") == 0)
		atacar(attributes);
	else if (name.compare("colocarEjercitos") == 0)
		colocarEjercitos(attributes);
	else if (name.compare("pasar") == 0)
		pasar(attributes);
	else if (name.compare("moverEjercitos") == 0)
			moverEjercitos(attributes);
	else if (name.compare("tirarDados") == 0)
		tirarDados(attributes);
	else if (name.compare("abandonar") == 0)
		abandonar(attributes);
}

void ParserDeJugadas::broadcastMensajeDeChat(const AttributeList& attributes) {
	MsgUtils msgutils;
	string remitente = "";
	string texto = "";
	for(xmlpp::SaxParser::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
		if (iter->name.compare("remitente") == 0)
			remitente = iter->value;
		else if (iter->name.compare("texto") == 0)
			texto = iter->value;
	this->juego->hablar(remitente,texto);
}

void ParserDeJugadas::unirse(const AttributeList& attributes) {
	string nombre = "";
	string color = "";
	for(xmlpp::SaxParser::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) {
		if (iter->name.compare("nombre") == 0)
			nombre = iter->value;
		else if (iter->name.compare("color") == 0)
			color = iter->value;
	}
	if (this->jugador == NULL)
		this->juego->unirse(this->juego->getFabricaDeJugadores()->crearJugador(nombre,color));
	else {
		this->jugador->setNombre(nombre);
		this->jugador->setColor(color);
		this->juego->unirse(jugador);
		this->juego->getServer()->enviarMensaje(jugador,"<unirseOk></unirseOk>");
	}
}

void ParserDeJugadas::tirarDados(const AttributeList& properties) {
	unsigned int dados;
	string color = "";
	for(xmlpp::SaxParser::AttributeList::const_iterator iter = properties.begin(); iter != properties.end(); ++iter) {
		if (iter->name.compare("jugador") == 0) {
			color = iter->value;
		}
		else if (iter->name.compare("cantidad") == 0)
			dados = atoi(iter->value.data());
	}
	if (this->jugador == NULL)
		juego->tirarDados(juego->getJugador(color),dados);
	else
		juego->tirarDados(jugador,dados);
}

void ParserDeJugadas::pasar(const AttributeList& properties) {
	string color = "";
	for(xmlpp::SaxParser::AttributeList::const_iterator iter = properties.begin(); iter != properties.end(); ++iter)
		if (iter->name.compare("jugador") == 0) {
			color = iter->value;
		}
	if (this->jugador == NULL)
		juego->pasar(juego->getJugador(color));
	else
		juego->pasar(jugador);
}

void ParserDeJugadas::atacar(const AttributeList& properties) {
	Territorio* territorioJugador;
	Territorio* territorioEnemigo;
	int cantidadDeEjercitos;
	string color = "";
	for(xmlpp::SaxParser::AttributeList::const_iterator iter = properties.begin(); iter != properties.end(); ++iter){
		if (iter->name.compare("jugador") == 0)
			color = iter->value;
		else if (iter->name.compare("territorioAtacante") == 0)
			territorioJugador = juego->getMapa()->obtenerTerritorio(iter->value);
		else if (iter->name.compare("territorioEnemigo") == 0)
				territorioEnemigo = juego->getMapa()->obtenerTerritorio(iter->value);
		else if (iter->name.compare("cantidadDeEjercitos") == 0)
				cantidadDeEjercitos = atoi(iter->value.data());
	}
	//TODO::Validar que si jugador==NULL entonces color != ""
	Ataque* ataque;
	if (this->jugador == NULL)
		ataque = new Ataque(juego->getJugador(color),territorioJugador,territorioEnemigo,cantidadDeEjercitos);
	else
		ataque = new Ataque(this->jugador,territorioJugador,territorioEnemigo,cantidadDeEjercitos);
	juego->realizarAtaque(ataque);
}

void ParserDeJugadas::moverEjercitos(const AttributeList& properties) {
	Territorio* origen;
	Territorio* destino;
	int cantidadDeEjercitos;
	string color = "";
	for(xmlpp::SaxParser::AttributeList::const_iterator iter = properties.begin(); iter != properties.end(); ++iter){
		if (iter->name.compare("jugador") == 0)
			color = iter->value;
		else if (iter->name.compare("origen") == 0)
			origen = juego->getMapa()->obtenerTerritorio(iter->value);
		else if (iter->name.compare("destino") == 0)
				destino = juego->getMapa()->obtenerTerritorio(iter->value);
		else if (iter->name.compare("cantidad") == 0)
				cantidadDeEjercitos = atoi(iter->value.data());
	}
	if (this->jugador == NULL)
		juego->moverEjercitos(juego->getJugador(color),origen,destino,cantidadDeEjercitos);
	else
		juego->moverEjercitos(jugador,origen,destino,cantidadDeEjercitos);
}

void ParserDeJugadas::colocarEjercitos(const AttributeList& properties) {
	Territorio* territorioJugador;
	int cantidadDeEjercitos;
	string color = "";
	for(xmlpp::SaxParser::AttributeList::const_iterator iter = properties.begin(); iter != properties.end(); ++iter){
		if (iter->name.compare("jugador") == 0)
			color = iter->value;
		else if (iter->name.compare("territorio") == 0)
			territorioJugador = juego->getMapa()->obtenerTerritorio(iter->value);
		else if (iter->name.compare("cantidad") == 0)
				cantidadDeEjercitos = atoi(iter->value.data());
	}
	if (this->jugador == NULL)
		juego->colocarEjercitos(juego->getJugador(color),territorioJugador,cantidadDeEjercitos);
	else
		juego->colocarEjercitos(jugador,territorioJugador,cantidadDeEjercitos);
}

void ParserDeJugadas::abandonar(const AttributeList& properties) {
	string color = "";
	for(xmlpp::SaxParser::AttributeList::const_iterator iter = properties.begin(); iter != properties.end(); ++iter) {
		if (iter->name.compare("jugador") == 0) {
			color = iter->value;
		}
	}
	if (this->jugador == NULL)
		juego->abandonar(juego->getJugador(color));
	else
		juego->abandonar(jugador);
}

void ParserDeJugadas::on_end_element(const Glib::ustring& name)
{
}


void ParserDeJugadas::on_characters(const Glib::ustring& text)
{
}

void ParserDeJugadas::on_comment(const Glib::ustring& text)
{
}

void ParserDeJugadas::on_warning(const Glib::ustring& text)
{
  std::cout << "on_warning(): " << text << std::endl;
}

void ParserDeJugadas::on_error(const Glib::ustring& text)
{
  std::cout << "on_error(): " << text << std::endl;
}

void ParserDeJugadas::on_fatal_error(const Glib::ustring& text)
{
  std::cout << "on_fatal_error(): " << text << std::endl;
}



